package com.da.core;

import com.da.core.state.JsonParser;

import java.lang.reflect.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * JSON到JavaBean的映射工具类（线程安全）
 *
 * @author da
 * @time 2025/3/5 下午 3:43
 */
public class JsonMapperUtil {
    // 预定义的JSON解析器实例（静态不可变）
    private static final JsonParser JSON_PARSER = new JsonParser();

    // 默认日期格式（SimpleDateFormat非线程安全，需配合ThreadLocal使用）
    private static final ThreadLocal<SimpleDateFormat> DATE_FORMATTER =
            ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

    /**
     * 禁止实例化工具类
     */
    private JsonMapperUtil() {
        throw new AssertionError("工具类禁止实例化");
    }

    /**
     * 将JSON字符串转换为指定类型的JavaBean对象
     *
     * @param json  符合格式要求的JSON字符串
     * @param clazz 目标Java类型Class对象
     * @param <T>   目标泛型类型
     * @return 完全初始化的JavaBean实例
     * @throws JSONParseException 当解析失败时抛出
     */
    public static <T> T fromJson(String json, Class<T> clazz) {
        Object parsed = JSON_PARSER.parse(json);
        try {
            if (parsed instanceof JsonObject) {
                return mapToBean((JsonObject) parsed, clazz);
            }
            throw new JSONParseException("根元素必须是JSON对象");
        } catch (ReflectiveOperationException e) {
            throw new JSONParseException("反射操作失败: " + e.getMessage(), e);
        } catch (Exception e) {
            throw new JSONParseException("JSON映射失败: " + e.getMessage(), e);
        }
    }

    /**
     * 递归映射JSON对象到JavaBean
     *
     * @param object 要映射的JSON对象
     * @param clazz  目标Java类型Class对象
     * @param <T>    目标泛型类型
     * @return 完全初始化的JavaBean实例
     */
    private static <T> T mapToBean(JsonObject object, Class<T> clazz)
            throws ReflectiveOperationException, Exception {

        // 通过反射创建目标对象实例
        T instance = clazz.getDeclaredConstructor().newInstance();

        // 遍历类的所有声明字段进行赋值
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);  // 突破私有字段访问限制
            String fieldName = field.getName();

            if (object.containsKey(fieldName)) {
                Object jsonValue = object.get(fieldName);
                Object javaValue = convertJsonValue(jsonValue, field);
                field.set(instance, javaValue);
            }
        }
        return instance;
    }

    /**
     * 智能转换JSON值到Java类型
     *
     * @param jsonValue JSON原始值对象
     * @param field     目标字段的反射对象
     * @return 类型适配后的Java对象
     */
    private static Object convertJsonValue(Object jsonValue, Field field) throws Exception {
        if (jsonValue == null) return null;

        Class<?> targetType = field.getType();
        // 优先处理集合类型
        if (List.class.isAssignableFrom(targetType)) {
            return convertList((JsonArray) jsonValue, field);
        }

        // 处理嵌套对象
        if (jsonValue instanceof JsonObject) {
            return mapToBean((JsonObject) jsonValue, targetType);
        }

        // 处理基础类型和字符串
        return convertBasicType(jsonValue, targetType);
    }

    /**
     * 转换JSON数组到Java集合
     *
     * @param jsonArray JSON数组对象
     * @param field     目标字段的反射对象
     * @param <T>       集合元素类型
     * @return 类型正确集合实例
     */
    @SuppressWarnings("unchecked")
    private static <T> List<T> convertList(JsonArray jsonArray, Field field) {
        //获取泛型类型
        Type genericType = field.getGenericType();

        if (!(genericType instanceof ParameterizedType)) {
            throw new JSONParseException("集合字段缺少泛型参数: " + field.getName());
        }

        ParameterizedType pType = (ParameterizedType) genericType;
        Type[] typeArgs = pType.getActualTypeArguments();

        if (typeArgs.length == 0) {
            throw new JSONParseException("集合缺少元素类型定义: " + field.getName());
        }

        // 获取集合元素的Class类型
        Type elementType = typeArgs[0];
        if (!(elementType instanceof Class)) {
            throw new JSONParseException("不支持的泛型类型: " + elementType.getTypeName());
        }

        @SuppressWarnings("unchecked")
        Class<T> elementClass = (Class<T>) elementType;

        // 流式处理集合元素转换
        return (List<T>) jsonArray.stream()
                .map(element -> {
                    try {
                        return convertBasicType(element, elementClass);
                    } catch (Exception e) {
                        throw new JSONParseException("集合元素转换失败", e);
                    }
                })
                .collect(Collectors.toList());
    }

    /**
     * 基础类型转换（包含常用类型处理）
     *
     * @param value      JSON原始值
     * @param targetType 目标Java类型
     * @return 类型转换后的对象
     */
    private static Object convertBasicType(Object value, Class<?> targetType) throws Exception {
        if (value == null) return null;

        // 处理字符串类型
        if (targetType == String.class) {
            return value.toString();
        }

        // 处理日期类型
        if (targetType == Date.class) {
            return parseDate(value.toString());
        }

        // 处理基本数据类型及其包装类
        if (targetType.isPrimitive() || isWrapperType(targetType)) {
            String stringValue = value.toString();
            return convertPrimitive(stringValue, targetType);
        }
        // 处理JsonObject
        if (value instanceof JsonObject) {
            return mapToBean((JsonObject) value, targetType);
        }
        // 其他类型
        throw new JSONParseException("不支持的类型: " + targetType.getName());
    }

    /**
     * 基本数据类型转换
     */
    private static Object convertPrimitive(String value, Class<?> targetType) {
        try {
            if (targetType == Integer.class || targetType == int.class) {
                return Integer.parseInt(value);
            }
            if (targetType == Long.class || targetType == long.class) {
                return Long.parseLong(value);
            }
            if (targetType == Double.class || targetType == double.class) {
                return Double.parseDouble(value);
            }
            if (targetType == Float.class || targetType == float.class) {
                return Float.parseFloat(value);
            }
            if (targetType == Boolean.class || targetType == boolean.class) {
                return Boolean.parseBoolean(value);
            }
            if (targetType == Short.class || targetType == short.class) {
                return Short.parseShort(value);
            }
            if (targetType == Byte.class || targetType == byte.class) {
                return Byte.parseByte(value);
            }
            if (targetType == Character.class || targetType == char.class) {
                return value.charAt(0);
            }
            // 处理其他未识别类型
            throw new JSONParseException("未支持的基本类型: " + targetType);

        } catch (NumberFormatException e) {
            throw new JSONParseException("数值格式错误: " + value, e);
        }
    }

    /**
     * 安全解析日期对象
     */
    private static Date parseDate(String dateString) {
        try {
            return DATE_FORMATTER.get().parse(dateString);
        } catch (ParseException e) {
            throw new JSONParseException("日期格式解析失败，期望格式: yyyy-MM-dd HH:mm:ss", e);
        }
    }

    /**
     * 判断是否为包装类型
     */
    private static boolean isWrapperType(Class<?> clazz) {
        return clazz == Integer.class || clazz == Long.class
                || clazz == Double.class || clazz == Float.class
                || clazz == Boolean.class || clazz == Short.class
                || clazz == Byte.class || clazz == Character.class;
    }
}